local base = game_mode.localbase
local mode = class("classic_mode",base)
mode.mapBuff = {}
mode.itemGenCD = 30
mode.itemGenTypes = {1,2,3,4,5,6,7}
mode.npcGenCD = 5
mode.npcGenTypes = {1,2,3,4,5,6,7,8}
mode.npcGenCollCheck = true
mode.npcGenMax = 30
mode.enablePlayerRebirth = true
mode.playerRebirthCD = 1
mode.playerBirthCollCheck = true
mode.playerGenTypes = {1}

local Item_classic = class("item_classic",Item)
Item_classic.collFunc = {
    function(game,tank) --shell
        sound:play("itemget")
        tank:takeShell()
    end,
    function(game,tank) --timer
        sound:play("itemget")
        for id, obj in pairs(game.objects) do
            if obj.tag == "tank" and obj.team~=tank.team then
                obj:poweroff(5)
            end
        end
    end,
    function(game,tank) --build
        sound:play("itemget")
        if tank == game.player then
            game.hq:build()
            delay:new(10,function()
                game.hq:normal()
            end)
        else
            game.hq:unbuild()
            delay:new(10,function()
                game.hq:normal()
            end)
        end
    end,
    function(game,tank) --upgrade
        sound:play("bonus")
        if tank == game.player then
            if tank.type >= 4 then
                sound:play("bonus")
                game.playerdata.life = game.playerdata.life + 1
            else
                sound:play("levelup")
                tank:changeType(tank.type+1)
            end
        else
            sound:play("levelup")
            tank:changeType(math.random(1,8))
        end
    end,
    function(game,tank) --boom
        sound:play("itemget")
        for id, obj in pairs(game.objects) do
            if obj.tag == "tank" and obj.team~=tank.team then
                obj:damage(tank)
            end
        end
    end,
    function(game,tank) --reinforce
        sound:play("bonus")
        if tank == game.player then
            game.playerdata.life = game.playerdata.life + 1
        else
            game.npcGenMax = game.npcGenMax + 10
        end
    end,
    function(game,tank) --gearup
        sound:play("levelup")
        tank:changeType(4)
    end,
}

local Tank_classic = class("tank_classic",Tank)
function Tank_classic:damage(bywho)
    if self.inShell then return end
    if self.game.player == self then
        if self.type > 1 then
            self:changeType(self.type-1)
        else
            self.game:onKill(bywho,self)
            self:destroy()
        end
    else
        self.life = self.life - 1
        if self.life == 0 then
            self.game:onKill(bywho,self)
            self:destroy()
        end
    end
end

function mode:init(playerdata)
    base.init(self)
    self.defaultAI = love.filesystem.read("res/tank.ai")
    self.playerdata = playerdata
    self:setMap(self.playerdata.stage)
    self:initItemGen()
    self:initNPCGen()
    self:setPlayerBirthPos()
    self.hq = HQ(self,13,self.map.h-1,2)
    self:setLocalObj(self.hq)
    self:setPlayerTank(self.playerdata)
end


function mode:update(dt)
    base.update(self,dt)
    self:updateItemGen(dt)
    self:updateNPCGen(dt)

    if self.hq.fallen and not self.gameovertag then
        self.gameovertag =true
        delay:new(2,function() self:gameover() end)
    end
end



function mode:draw()
    love.graphics.setColor(1, 1, 1, 1)
    local sw,sh = love.graphics.getDimensions()
    local data = string.format("敌军增援: %d, 我军增援 %d, 第%d要塞",
        self.npcGenMax-self.npcGenCount,self.playerdata.life,self.playerdata.stage)
    love.graphics.setFont(texture.tinyfont)
    love.graphics.printf(data, 0, 120, sw, "center")
    base.draw(self)
end

function mode:setMap(stage)
    local name = string.format("stage%02d",stage)
    local str_dat = love.filesystem.read("res/"..name..".dat")
    local map_dat = bitser.loads(str_dat)
    self.map:setData(map_dat)
end

function mode:loadAI(name)
    if not mode.aiBuff[name] then
        local f = io.open("client/res/"..name..".ai","r")
        local aiString = f:read("*a")
        f:close()
        mode.aiBuff[name] = aiString
    end
    return mode.aiBuff[name]
end

function mode:initItemGen(timeCD,types)
    if self.itemGenCD <= 0 then return end
    self.enableItemGen = true
   	self.itemGenTimer = self.itemGenCD
end

function mode:updateItemGen(dt)
    if not self.enableItemGen then return end
    self.itemGenTimer = self.itemGenTimer - dt
	if self.itemGenTimer<0 then
		self.itemGenTimer = self.itemGenCD
		local item = Item_classic(
            self,
			math.random(1,self.map.w*16),
			math.random(1,self.map.h*16),
			2,
			self.itemGenTypes[math.random(1,#self.itemGenTypes)]
		)
		self:setLocalObj(item)
	end
end

function mode:initNPCGen()
    if self.npcGenCD <= 0 then return end
    self.enableNPCGen = true
    self.npcGenTimer = self.npcGenCD
    self.npcGenCount = 0
    self.npc = {}
    self:setNPCGenPos()
end

function mode:setNPCGenPos()
    self.npcGenPos = {
        minX = 1,
        maxX = self.map.w-1,
        minY = 1,
        maxY = 1}
end

function mode:setNPCAI(aiString)
    self.npcAI = aiString
end

function mode:updateNPCGen(dt)
    if not self.enableNPCGen then return end
    self.npcGenTimer = self.npcGenTimer - dt
	if self.npcGenTimer<0 and self.npcGenMax > self.npcGenCount then
		self.npcGenTimer = self.npcGenCD
		local tank = self:newTank(
            2,
            self.npcGenTypes[math.random(1,#self.npcGenTypes)],
            self.npcGenPos,
            self.npcGenCollCheck)
		tank:setAI(self.npcAI or self.defaultAI)
		self:setLocalObj(tank)
        self.npcGenCount = self.npcGenCount + 1
        table.insert(self.npc,tank)
	end
end


function mode:setPlayerBirthPos() --被重写
    self.playerGenPos = {
        minX = 1,
        maxX = self.map.w-1,
        minY = self.map.h-1,
        maxY = self.map.h-1
        }
end

function mode:setPlayerTank(playerdata)
    local tank = self:newTank(
        1,
        self.playerGenTypes,
        self.playerGenPos,
        self.playerBirthCollCheck)
    print(tank)
    self:setPlayer(tank,self:newLocalID())
    playerdata.tank = tank
end
local colltag = {
    brick = true,
    iron = true,
    water = true,
    hq = true,
    tank = true,
    border = true
    }
local filter = function(other)
    return colltag[other.tag]
end
local filter_no_coll = function (other)
    return other.tag == "tank"
end

function mode:newTank(teams,types,pos,checkColl)
    local x,y
    local ix,iy
    while true do
        ix = math.random(pos.minX,pos.maxX)
        iy = math.random(pos.minY,pos.maxY)
        x = ix*16
        y = iy*16
        local colls,collCount = self.world:queryRect(x-16,y-16,32,32,
            checkColl and filter or filter_no_coll
        )
        if collCount == 0 then
            break
        end
    end
    if not checkColl then
        self.map:setTile(ix+1,iy,6)
        self.map:setTile(ix,iy,6)
        self.map:setTile(ix,iy+1,6)
        self.map:setTile(ix+1,iy+1,6)
    end
    
    local tank = Tank_classic(
            self,
			x, --x
			y,  --y
			math.random(0,3), --rot
			2, --scale
			type(teams) == "number" and teams or teams[math.random(1,#teams)], --team
			type(types) == "number" and types or types[math.random(1,#types)]--type
        )
    return tank
end

local scoreTypes = {
    [1] = 100,
    [2] = 200,
    [3] = 400,
    [4] = 800,
    [5] = 200,
    [6] = 300,
    [7] = 300,
    [8] = 1000
}

function mode:onKill(killer,victim)
    for i = #self.npc , 1 , - 1 do
        if self.npc[i] == victim then
            table.remove(self.npc,i)
        end
    end


    if killer == self.player then
        self.playerdata.score = self.playerdata.score + scoreTypes[victim.type]
    else
        if self.playerdata.life > 1 then
            self.playerdata.life = self.playerdata.life - 1
            delay:new(self.playerRebirthCD,
                function() self:setPlayerTank(self.playerdata) end)
        else
            delay:new(2,function() self:gameover() end)
        end
    end

    if self.npcGenCount == self.npcGenMax and 
        #self.npc == 0 then
        self.playerdata.stage = self.playerdata.stage + 1
        return gamestate.current():newStage()
    end
end

function mode:gameover()
    sound:stopAll()
    gamestate.switch(gameState.result,{you = "game over"})
end



return mode
